/*

Summary:
Used to convert between wide string and multi byte string.

Remark:
Encode and Decode both have two overrides: one have two arguments 
and none return value; another have one agument and one return value.
Always use the one argument override because it is more convenient to use.
Use the two arguments override only if the construction and destruction 
of string are costly.

Version:
0.1.1

LastUpdatedDate:
2012-07-13

*/

#pragma once
#include <string>
#include <Windows.h>

namespace Zaf {
namespace __Internal {

//Internal use only.
inline void __Encode(int codePage, const std::wstring& in, std::string& out) {

	int requireSize = WideCharToMultiByte(
		codePage, 
		0,
		in.c_str(),
		in.length(),
		nullptr,
		0,
		nullptr,
		nullptr
	);

	if (requireSize == 0) {
		return;
	}

	out.resize(requireSize);

	int encodeLen = WideCharToMultiByte(
		codePage,
		0,
		in.c_str(),
		in.length(),
		&out[0],
		requireSize,
		nullptr,
		nullptr
	);
}

//Internal use only.
inline void __Decode(int codePage, const std::string& in, std::wstring& out) {

	int requireSize = MultiByteToWideChar(
		codePage,
		0,
		in.c_str(),
		in.length(),
		nullptr,
		0
	);

	if (requireSize == 0) {
		return;
	}

	out.resize(requireSize);

	int decodeLen = MultiByteToWideChar(
		codePage,
		0,
		in.c_str(),
		in.length(),
		&out[0],
		requireSize
	);
}
}

struct Ansi { static const int CodePage = CP_ACP; };
struct Utf8 { static const int CodePage = CP_UTF8; };

template<typename Encoding>
inline void Encode(const std::wstring& in, std::string& out) {
	__Internal::__Encode(Encoding::CodePage, in, out);
}

template<typename Encoding>
inline std::string Encode(const std::wstring& in) {
	std::string out;
	__Internal::__Encode(Encoding::CodePage, in, out);
	return out;
}

template<typename Encoding>
inline void Decode(const std::string& in, std::wstring& out) {
	__Internal::__Decode(Encoding::CodePage, in, out);
}

template<typename Encoding>
inline std::wstring Decode(const std::string& in) {
	std::wstring out;
	__Internal::__Decode(Encoding::CodePage, in, out);
	return out;
}

};